package com.wenlin.myproduction.widget;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.wenlin.myproduction.R;
import com.wenlin.myproduction.bean.PrivateBean;
import com.wenlin.myproduction.util.FastBlur;

import java.io.File;
import java.util.List;

/**
 * @author cwl
 * @desc 思路：各个条目水平排成一条长排，离View的水平中心越近则越大，最大不能超过设定的最大值，越远则越小，最小不能小于原大小。
 * 这样看起来的效果是视图中间的条目放大，两边的正常。滑动时中间的条目逐渐恢复，靠近中间的条目逐渐放大。
 * 加了限制，真实手机上用户即使滑动一屏幕的宽度，也最多滑动一个条目（模拟器可滑动多个条目，导致动画有点奇怪，影响不大）。
 * <p>
 * 因为控件高度是根据手机的宽度计算出来的，而且控件左右的边距是写死的各16dp，所以使用时需要在布局中设置：
 * android:layout_width="match_parent"
 * android:layout_height="wrap_content"
 * android:layout_marginHorizontal="@dimen/left"
 */
public class PicVideoBannerView extends View {
    private final float BORDER_WIDTH_OF_BITMAP = dpToPx(4);
    private final float INDICATE_AREA_HEIGHT = dpToPx(20);
    private final float MARGIN_OF_PRIVATE_SMALL = dpToPx(5);
    private static final float MAX_RATIO = 1.367f;//大个的条目与正常大小的条目的比例
    private final float ROUND_RADIUS = dpToPx(15);//圆角半径
    private static final int ANIM_DUR = 500;
    private final float INDICATOR_HEIGHT = dpToPx(5);//指示点的高度即直径
    private final float INDICATOR_WIDTH = 3 * INDICATOR_HEIGHT;//当前的指示点的宽度
    @ColorInt
    private static final int COLOR_INDICATOR = Color.parseColor("#ffd1d1d1");
    @ColorInt
    private static final int COLOR_BORDER = Color.parseColor("#ffeaeaea");
    private int viewWidth;
    private final float MIN_SCROLL_DISTANCE = dpToPx(10);//大致上弄个值
    private final float MAX_CLICK_SCROLL_DISTANCE = dpToPx(5);//大致上弄个值
    private static final float PIC_RATIO = 150 / 120f;//图片的长宽比
    private float normalWidth;
    private float picWidth;
    private float picHeight;//图片的长宽比150：120
    private float normalHeight;
    private int viewHeight;
    private float centerPicsY;//图片集的中间点的XY坐标
    private float centerPicsX;
    private Bitmap bitmapPlay, bitmapPrivate, bitmapPrivateSmall;
    private List<PrivateBean> list;
    private Paint paint, paintBg;
    private Path path;
    private PorterDuffXfermode porterDuffXfermode;
    private RectF rectF;
    private ValueAnimator valueAnimator;//值动画
    private boolean showHelpLines = false;//是否显示辅助线
    private float scrollXOffset;//滑动偏移值
    private float lastX;//上一个手指按下的x坐标
    private float valueFloat;//动画用到的值
    private int centerItemIndex;
    private int currentIndex = 1;//当前最大的条目的脚标
    private int handleBitmapIndex;//处理位图的脚标
    private onItemClickListener listener;
    private boolean isOwner;//是否是主人，是的话私密照片不显示模糊图片，而是显示私密图标

    public PicVideoBannerView(Context context) {
        this(context, null);
    }

    public PicVideoBannerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    //region 私有方法

    /**
     * 初始化
     */
    private void init() {
        //画笔
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setStyle(Paint.Style.FILL);

        paintBg = new Paint();
        paintBg.setAntiAlias(true);
        paintBg.setDither(true);
        paintBg.setColor(COLOR_BORDER);
        paintBg.setStyle(Paint.Style.STROKE);
        paintBg.setStrokeCap(Paint.Cap.ROUND);
        paintBg.setStrokeWidth(BORDER_WIDTH_OF_BITMAP);
        //
        path = new Path();
        rectF = new RectF();
        //裁剪模式
        porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);//模式：显示前景图并取交集（IN）。（SRC source表示源图片，背景图是DST destination目的地）
        //
        bitmapPlay = BitmapFactory.decodeResource(getResources(), R.mipmap.common_btn_play);
        bitmapPrivate = BitmapFactory.decodeResource(getResources(), R.mipmap.common_icon_private_big_gray);
        bitmapPrivateSmall = BitmapFactory.decodeResource(getResources(), R.mipmap.icon_photo_private);

//        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();
//        viewWidth = (int) (dpToPx(getResources().getConfiguration().screenWidthDp)) - params.leftMargin - params.rightMargin - getPaddingLeft() - getPaddingRight();
        viewWidth = (int) dpToPx(getResources().getConfiguration().screenWidthDp);
        normalWidth = viewWidth / 3f;
        picWidth = normalWidth - BORDER_WIDTH_OF_BITMAP;
        picHeight = picWidth * PIC_RATIO;
        normalHeight = picHeight + BORDER_WIDTH_OF_BITMAP;
        viewHeight = (int) (picHeight * MAX_RATIO + BORDER_WIDTH_OF_BITMAP * 2 + INDICATE_AREA_HEIGHT);
        centerPicsY = (viewHeight - INDICATE_AREA_HEIGHT) / 2f;
        centerPicsX = viewWidth / 2f;
//        fakeData();
    }

    /**
     * 更新数据
     */
    private void updateData() {
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                if (i == currentIndex) {
                    list.get(i).setRatio(MAX_RATIO);
                    list.get(i).setWidth(normalWidth * MAX_RATIO);
                    list.get(i).setOldWidth(normalWidth * MAX_RATIO);
                    list.get(i).setCenterX(centerPicsX);
                    list.get(i).setOldCenterX(centerPicsX);
                } else {
                    list.get(i).setRatio(1);
                    list.get(i).setWidth(normalWidth);
                    list.get(i).setOldWidth(normalWidth);
                    list.get(i).setCenterX(centerPicsX + (i - currentIndex) * normalWidth);
                    list.get(i).setOldCenterX(centerPicsX + (i - currentIndex) * normalWidth);
                }
            }
        }
    }

    /**
     * 处理位图，包括调整尺寸、模糊处理
     * TODO 改成异步的，只要有图片处理完成，就更新显示出来，而不是全部处理完成才统一显示
     */
    private void handleBitmap() {
        if (list == null) return;
        if (handleBitmapIndex >= list.size()) {
            postInvalidate();
            return;
        }
//        long time = System.currentTimeMillis();
        new Handler().post(() -> Glide.with(getContext()).downloadOnly().load(list.get(handleBitmapIndex).getCover()).into(new SimpleTarget<File>() {
            @Override
            public void onResourceReady(@NonNull File resource, @Nullable Transition<? super File> transition) {
                Bitmap bitmap = BitmapFactory.decodeFile(resource.getAbsolutePath());
                if (bitmap != null) {
                    float ratio = bitmap.getHeight() / (float) bitmap.getWidth();//长宽比
                    if (ratio > PIC_RATIO) {//长图，宽度撑死picWidth，高度放大
                        bitmap = getBitmapWithTargetWidthHeight(bitmap, picWidth, picHeight * (ratio / PIC_RATIO));
                    } else if (ratio > 0) {//宽图，高度撑死picHeight，宽度放大
                        bitmap = getBitmapWithTargetWidthHeight(bitmap, picWidth / (ratio / PIC_RATIO), picHeight);
                    }
                    //非主人且是私密照片
                    if (!isOwner && list.get(handleBitmapIndex).isPrivate()) {
                        bitmap = FastBlur.blur(bitmap, 20, true);
//                        LogU.v("cost " + (System.currentTimeMillis() - time));
                    }
                    list.get(handleBitmapIndex).setBitmap(bitmap);
//                    LogShow.v(bitmap, bitmap.getWidth(), bitmap.getHeight());
                }
                handleBitmapIndex++;
                handleBitmap();
            }

            @Override
            public void onLoadFailed(@Nullable Drawable errorDrawable) {
                super.onLoadFailed(errorDrawable);
                handleBitmapIndex++;
                handleBitmap();
            }
        }));
    }

    /**
     * 格式化缩放比例
     *
     * @param ratio 缩放比例
     * @return 所求
     */
    private float formatRatio(float ratio) {
        if (ratio < 1) ratio = 1;
        if (ratio > MAX_RATIO) ratio = MAX_RATIO;
        return ratio;
    }

    /**
     * 设置数据并滑动到指定位置
     *
     * @param newList      新的数据集合
     * @param currentIndex 当前位置
     */
    private void setData(List<PrivateBean> newList, int currentIndex) {
        list = newList;
        this.currentIndex = currentIndex;
        updateData();
        handleBitmapIndex = 0;
        handleBitmap();
        scrollXOffset = 0;
    }

    /**
     * 设置滑动偏移
     */
    private void setAllXOffset() {
        if (list == null || list.size() == 0) return;
        float centerX;
        float ratio;
        float width;
        for (int i = 0; i < list.size(); i++) {
            centerX = list.get(i).getOldCenterX() + scrollXOffset;
            list.get(i).setCenterX(centerX);
            ratio = formatRatio(MAX_RATIO - Math.abs(centerX - centerPicsX) / (normalWidth / 2f) * MAX_RATIO);//越接近水平中心则越大
            list.get(i).setRatio(ratio);
            width = ratio * normalWidth;
            list.get(i).setWidth(width);
        }
    }

    /**
     * 自动跳到触摸点上的条目，如果是滑动，则滑到合适的条目
     *
     * @param x 触摸点的横坐标
     */
    private void autoSwitchItem(float x, float y) {
        boolean findItemAlready = false;
        if (list == null || list.size() == 0) return;
        for (int i = 0; i < list.size(); i++) {
            PrivateBean bean = list.get(i);
            float centerX = bean.getCenterX();//找到中间线的横坐标
            if (Math.abs(scrollXOffset) < MIN_SCROLL_DISTANCE) {//在一个10的范围内的滑动视为点击而不是滑动
                if ((centerX - bean.getWidth() / 2f) < x && (centerX + bean.getWidth() / 2f) > x) {//如果找到了手指下的条目     && y < centerPicsY + bean.getRatio() * normalHeight / 2f && y > centerPicsY - bean.getRatio() * normalHeight / 2f
                    boolean clickSmallItemAndStartActivity = false;
                    if (centerX > centerPicsX - normalWidth / 2f && centerX < centerPicsX + normalWidth / 2f) {//点了中间的条目
                        startAnimator(scrollXOffset, 0);
                        currentIndex = i;
//                        LogU.v("落在中间");
                    } else if (centerX > 0 && centerX < centerPicsX - normalWidth / 2f) {
                        startAnimator(scrollXOffset, normalWidth);
                        currentIndex = i;
                        clickSmallItemAndStartActivity = true;
//                        LogU.v("落在相邻左边");
                    } else if (centerX > centerPicsX + normalWidth / 2f && centerX < viewWidth) {
                        startAnimator(scrollXOffset, -normalWidth);
                        currentIndex = i;
                        clickSmallItemAndStartActivity = true;
//                        LogU.v("落在相邻右边");
                    } else {//先前没有这个else{}的代码，加上这个可以修复滑动小距离时不会自动滑到目标条目的问题
                        startAnimator(scrollXOffset, 0);
                        currentIndex = i;
//                        LogU.v("落在剩余位置");
                    }
                    findItemAlready = true;
                    if (Math.abs(scrollXOffset) < MAX_CLICK_SCROLL_DISTANCE) {
                        //点击事件
                        if (listener != null) {
                            if (isOwner || !bean.isPrivate()) {//点击了公开的内容
                                if (clickSmallItemAndStartActivity)//如果点了小条目，并且此时小条目是可读的，则先滑动到左侧变成大条目，再去做跳转操作，避免跳转操作和滑动操作同时进行，造成控件卡顿
                                    postDelayed(() -> listener.onClickWithUnlock(bean, currentIndex), ANIM_DUR);
                                else
                                    listener.onClickWithUnlock(bean, currentIndex);
                            } else {//点击了私密的内容
                                listener.onClickWithLock(bean, currentIndex);
                            }
                        }
                    }
//                    LogU.v("点击currentIndex=" + currentIndex);
                    break;
                }
            } else if (scrollXOffset > MIN_SCROLL_DISTANCE) {//向右滑动，找中间左边相邻的条目
                if (centerX > centerPicsX - bean.getWidth() && centerX < centerPicsX) {
                    currentIndex = i;
//                    LogU.v("右滑currentIndex=" + currentIndex);
                    startAnimator(scrollXOffset, normalWidth);
                    findItemAlready = true;
                    break;
                }
            } else if (scrollXOffset < -MIN_SCROLL_DISTANCE) {//向左滑动，找中间右边相邻的条目
                if (centerX > centerPicsX && centerX < centerPicsX + bean.getWidth()) {
                    currentIndex = i;
//                    LogU.v("左滑currentIndex=" + currentIndex);
                    startAnimator(scrollXOffset, -normalWidth);
                    findItemAlready = true;
                    break;
                }
            }
        }
        //前面的情况都不符合，说明是第一个往右滑或者最后一个往左滑的情况，或者是在滑到最后一个条目后，直接点击了空白
        if (!findItemAlready) {
            //如果点击的是最后一个计划右边的空白
            if (Math.abs(scrollXOffset) < MAX_CLICK_SCROLL_DISTANCE) {
                //点击事件
                if (x > normalWidth)
                    return;//如果点击的是空白，就不做动作
            }
            if (scrollXOffset >= 0) {
                currentIndex = 0;
            } else {
                currentIndex = list.size() - 1;
            }
            startAnimator(scrollXOffset, 0);
        }
    }

    /**
     * 开始动画
     *
     * @param start 动画的初始值
     * @param end   动画的结束值
     */
    private void startAnimator(float start, float end) {
        if (valueAnimator != null && valueAnimator.isRunning()) return;
        valueAnimator = ValueAnimator.ofFloat(start, end);
        valueAnimator.addUpdateListener(animation -> {
            valueFloat = (float) animation.getAnimatedValue();
            scrollXOffset = valueFloat;
            setAllXOffset();
            invalidate();
        });
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //同步新数据覆盖旧数据
                scrollXOffset = 0;
                updateData();
                invalidate();
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        double time = Math.ceil(Math.abs(end - start)) / normalWidth * ANIM_DUR;
        valueAnimator.setDuration((int) time);
        valueAnimator.start();
    }

    /**
     * 生成新的Bitmap图片
     *
     * @return 所求
     */
    private Bitmap getBitmapWithTargetWidthHeight(Bitmap bitmap, float newWidth, float newHeight) {
        Matrix matrix = new Matrix();
        int width = bitmap.getWidth();//获取图片本身的宽
        int height = bitmap.getHeight();//获取图片本身的高
        float scaleRatioOfWidth = newWidth / (width > 0 ? width : newWidth);//宽度缩放比
        float scaleRatioOfHeight = newHeight / (height > 0 ? height : newHeight);//高度缩放比
        matrix.postScale(scaleRatioOfWidth, scaleRatioOfHeight);
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    }

    /**
     * 尝试画放大的条目
     *
     * @param canvas 画布
     * @param bean   条目对象
     */
    private void tryDrawScaleItem(Canvas canvas, PrivateBean bean) {
        if (bean != null && bean.getBitmap() != null && !bean.getBitmap().isRecycled()) {
            canvas.save();
            canvas.scale(bean.getRatio(), bean.getRatio(), bean.getCenterX(), centerPicsY);
            drawItem(canvas, bean);
            canvas.restore();
        }
    }

    /**
     * 画条目
     *
     * @param canvas 画布
     * @param bean   条目对象
     */
    private void drawItem(Canvas canvas, PrivateBean bean) {
        //先画圆角矩形的path
        path.reset();
        //从左上角圆角的尾巴开始，按照顺时针进行绘制
        path.moveTo(bean.getCenterX() - picWidth / 2f + ROUND_RADIUS, centerPicsY - picHeight / 2f);
        path.lineTo(bean.getCenterX() + picWidth / 2f - ROUND_RADIUS, centerPicsY - picHeight / 2f);
        //右上角圆角
        rectF.set(bean.getCenterX() + picWidth / 2f - ROUND_RADIUS * 2, centerPicsY - picHeight / 2f, bean.getCenterX() + picWidth / 2f, centerPicsY - picHeight / 2f + ROUND_RADIUS * 2);
        path.arcTo(rectF, -90, 90);
        //右边
        path.lineTo(bean.getCenterX() + picWidth / 2f, centerPicsY + picHeight / 2f - ROUND_RADIUS);
        //右下角圆角
        rectF.set(bean.getCenterX() + picWidth / 2f - ROUND_RADIUS * 2, centerPicsY + picHeight / 2f - ROUND_RADIUS * 2, bean.getCenterX() + picWidth / 2f, centerPicsY + picHeight / 2f);
        path.arcTo(rectF, 0, 90);
        //下边
        path.lineTo(bean.getCenterX() - picWidth / 2f + ROUND_RADIUS, centerPicsY + picHeight / 2f);
        //左下角圆角
        rectF.set(bean.getCenterX() - picWidth / 2f, centerPicsY + picHeight / 2f - ROUND_RADIUS * 2, bean.getCenterX() - picWidth / 2f + ROUND_RADIUS * 2, centerPicsY + picHeight / 2f);
        path.arcTo(rectF, 90, 90);
        //左边
        path.lineTo(bean.getCenterX() - picWidth / 2f, centerPicsY - picHeight / 2f + ROUND_RADIUS);
        //左上角圆角
        rectF.set(bean.getCenterX() - picWidth / 2f, centerPicsY - picHeight / 2f, bean.getCenterX() - picWidth / 2f + ROUND_RADIUS * 2, centerPicsY - picHeight / 2f + ROUND_RADIUS * 2);
        path.arcTo(rectF, 180, 90);
        path.close();
        canvas.drawPath(path, paintBg);
        canvas.saveLayerAlpha(bean.getCenterX() - picWidth / 2f,
                centerPicsY - picHeight / 2f,
                bean.getCenterX() + picWidth / 2f,
                centerPicsY + picHeight / 2f, 255);
        canvas.drawPath(path, paint);
        paint.setXfermode(porterDuffXfermode);
        canvas.drawBitmap(bean.getBitmap(), bean.getCenterX() - bean.getBitmap().getWidth() / 2f, centerPicsY - bean.getBitmap().getHeight() / 2f, paint);
        paint.setXfermode(null);
        canvas.restore();
        //画图标
        if (bean.isPrivate()) {//私密图标
            if (isOwner)//图片右上角的小图标
                canvas.drawBitmap(bitmapPrivateSmall, bean.getCenterX() + picWidth / 2f - MARGIN_OF_PRIVATE_SMALL - bitmapPrivateSmall.getWidth(), centerPicsY - picHeight / 2f + MARGIN_OF_PRIVATE_SMALL, paint);
            else//图片中间的大图标
                canvas.drawBitmap(bitmapPrivate, bean.getCenterX() - bitmapPrivate.getWidth() / 2f, centerPicsY - bitmapPrivate.getHeight() / 2f, paint);
        } else if (bean.isVideo()) {//如果是视频，则显示播放按钮
            canvas.drawBitmap(bitmapPlay, bean.getCenterX() - bitmapPlay.getWidth() / 2f, centerPicsY - bitmapPlay.getHeight() / 2f, paint);
        }
        //辅助线
        if (showHelpLines)
            canvas.drawLine(bean.getCenterX(), 0, bean.getCenterX(), viewHeight, paintBg);
    }

    /**
     * 画指示点
     *
     * @param canvas 画布
     */
    private void drawIndicator(Canvas canvas) {
        if (list == null || list.size() <= 0) return;
        float width = INDICATOR_WIDTH + 2 * INDICATOR_HEIGHT * list.size() - 1 + INDICATOR_HEIGHT;
        float temp = viewWidth / 2f - width / 2f;
        paint.setColor(COLOR_INDICATOR);
        for (int i = 0; i < list.size(); i++) {
            temp += INDICATOR_HEIGHT / 2f;
            if (i == currentIndex) {
                canvas.drawRoundRect(temp, viewHeight - INDICATE_AREA_HEIGHT / 2f - INDICATOR_HEIGHT / 2f, temp + INDICATOR_WIDTH, viewHeight - INDICATE_AREA_HEIGHT / 2f + INDICATOR_HEIGHT / 2f, INDICATOR_HEIGHT / 2f, INDICATOR_HEIGHT / 2f, paint);
                temp += INDICATOR_WIDTH;
            } else {
                canvas.drawRoundRect(temp, viewHeight - INDICATE_AREA_HEIGHT / 2f - INDICATOR_HEIGHT / 2f, temp + INDICATOR_HEIGHT, viewHeight - INDICATE_AREA_HEIGHT / 2f + INDICATOR_HEIGHT / 2f, INDICATOR_HEIGHT / 2f, INDICATOR_HEIGHT / 2f, paint);
                temp += INDICATOR_HEIGHT;
            }
            temp += INDICATOR_HEIGHT / 2f;
        }
    }

    /**
     * 转化长度单位
     *
     * @param dp dp长度
     * @return 对应的px长度
     */
    private float dpToPx(float dp) {
        float scale = getResources().getDisplayMetrics().density;
        return dp * scale;
    }

    //endregion

    //region 暴露公共方法

    /**
     * 设置点击条目的监听
     *
     * @param listener 点击监听
     */
    public void setOnItemClickListener(onItemClickListener listener) {
        this.listener = listener;
        invalidate();
    }

    /**
     * 设置是否是主人，是主人则不用模糊图片，点击后可直接查看详情
     *
     * @param isOwner 是否是主人
     */
    public void setOwner(boolean isOwner) {
        this.isOwner = isOwner;
        invalidate();
    }

    /**
     * 设置私密内容
     *
     * @param privateBeanList 私密内容集合
     */
    public void setPrivateList(List<PrivateBean> privateBeanList) {
        resetData(privateBeanList, privateBeanList.size() > 1 ? 1 : 0);
    }

    /**
     * 重置数据，先清空数据再添加新的数据
     *
     * @param newList      新的数据集合
     * @param currentIndex 当前选中条目的脚标
     */
    public void resetData(List<PrivateBean> newList, int currentIndex) {
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                PrivateBean temp = list.get(i);
                Bitmap bitmap = temp.getBitmap();
                if (bitmap != null && !bitmap.isRecycled()) {
                    bitmap.recycle();
                    bitmap = null;
                    list.get(i).setBitmap(null);
                }
            }
        }
        setData(newList, currentIndex);
    }

    //endregion

    //region 重写方法
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
    }

    /**
     * 获取宽或者高
     *
     * @param measureSpec 测量单位
     * @param isWidSpec   是宽还是高
     * @return 所求
     */
    private int measure(int measureSpec, boolean isWidSpec) {
        int result;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = isWidSpec ? viewWidth : viewHeight;
            if (mode == MeasureSpec.AT_MOST) result = Math.min(result, size);
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (list == null || list.size() <= 0) return;
        //画除了居中的item之外的剩余的item
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getCenterX() > centerPicsX - normalWidth / 2f && list.get(i).getCenterX() < centerPicsX + normalWidth / 2f) {
                centerItemIndex = i;
                continue;//离水平中心最近的item跳过，最后再画，避免被遮挡
            }
            tryDrawScaleItem(canvas, list.get(i));
        }
        //画居中的item，保证居中的item不被遮挡
        if (centerItemIndex < list.size()) {
            tryDrawScaleItem(canvas, list.get(centerItemIndex));
        }
        drawIndicator(canvas);
        //辅助线
        if (showHelpLines) {
            canvas.drawLine(viewWidth / 2f, 0, viewWidth / 2f, viewHeight, paintBg);
            canvas.drawLine(0, centerPicsY, viewWidth, centerPicsY, paintBg);
            canvas.drawLine(0, 0, 0, getHeight(), paintBg);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (valueAnimator != null && valueAnimator.isRunning()) return super.onTouchEvent(event);
        float x = event.getX();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://按下手指记录x坐标
                lastX = x;
                return true;
            case MotionEvent.ACTION_MOVE://滑动时计算滑动偏移值并且设置所有的条目的x坐标，实时更新
                scrollXOffset = x - lastX;
                scrollXOffset *= normalWidth / viewWidth;//避免滑过两个item导致错位。而且加上这个还带点视差效果
                setAllXOffset();
                invalidate();
                return true;
            case MotionEvent.ACTION_UP://手指抬起时，根据x坐标，自动判断目标条目，并进行动画滑动到目标条目
                autoSwitchItem(x, event.getY());
                performClick();
                return true;
            default:
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                PrivateBean temp = list.get(i);
                if (temp.getBitmap() != null && !temp.getBitmap().isRecycled()) {
                    temp.getBitmap().recycle();
                    temp.setBitmap(null);
                    list.get(i).setBitmap(null);
                }
            }
        }
        if (bitmapPlay != null && !bitmapPlay.isRecycled()) {
            bitmapPlay.recycle();
            bitmapPlay = null;
        }
        if (bitmapPrivate != null && !bitmapPrivate.isRecycled()) {
            bitmapPrivate.recycle();
            bitmapPrivate = null;
        }
        if (bitmapPrivateSmall != null && !bitmapPrivateSmall.isRecycled()) {
            bitmapPrivateSmall.recycle();
            bitmapPrivateSmall = null;
        }
    }

    //endregion

    //region 回调接口

    /**
     * 回调接口
     */
    public interface onItemClickListener {
        /**
         * 点击未锁定（即已公开）的内容
         */
        void onClickWithUnlock(PrivateBean bean, int currentIndex);

        /**
         * 点击已锁定（即未公开）的内容
         */
        void onClickWithLock(PrivateBean bean, int currentIndex);
    }

    //endregion
}
